#include <stdafx.h>
#include "PhysicsViewport.h"
#include "LitPhysicsBody.h"
#include <LitCore.h>
#include <LitSceneManager.h>
#include <LitPhysicsManager.h>

PhysicsViewport::PhysicsViewport( QWidget*parent ) 
	: OgreSubWidget(parent)
{
	setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
	setMinimumSize( 128, 128 );

	connect( (OgreSubWidget*)this, SIGNAL(ogreInitialise()), this, SLOT(ogreInitialise()) );
	connect( (OgreSubWidget*)this, SIGNAL(ogreShutdown()), this, SLOT(ogreShutdown()) );
}
PhysicsViewport::~PhysicsViewport()
{
}

void PhysicsViewport::createScene( )
{
	mFloor = Lit::EntityPtr( Lit::Root::SceneManager()->createEntity("floorMesh", NULL, mSceneManager) );
	mFloorBody = Lit::Root::PhysicsManager()->createWorld( "PHYSICS" )->createStaticBody( *mFloor, Lit::Physics::ST_PLANE, 0 );
	
}
void PhysicsViewport::destroyScene( )
{
	if( mFloor )
		Lit::Root::SceneManager()->removeEntity( mFloor->getName() );
}

void PhysicsViewport::ogreInitialise()
{
	mRoot->addFrameListener( this );
}
void PhysicsViewport::ogreShutdown()
{
	mRoot->removeFrameListener( this );
}

bool PhysicsViewport::frameRenderingQueued( const Ogre::FrameEvent& evt )
{
	if( mEntity )
	{
		mEntity->getNode()->pitch( Ogre::Degree(mDrag.Delta.y())*evt.timeSinceLastFrame );
		mEntity->getNode()->yaw( Ogre::Degree(mDrag.Delta.x())*evt.timeSinceLastFrame );
	}
	return true;
}
	
void PhysicsViewport::mousePressEvent( QMouseEvent*evt )
{
	mDrag.mousePressed( evt->pos(), evt->buttons() );
}
void PhysicsViewport::mouseMoveEvent( QMouseEvent*evt )
{
	mDrag.mouseMoved( evt->pos(), evt->buttons() );
}
void PhysicsViewport::mouseReleaseEvent( QMouseEvent*evt )
{
	mDrag.mouseReleased( evt->pos(), evt->buttons() );
}
void PhysicsViewport::fitEntity() 
{
	if( !mEntity )
		return;
	Ogre::AxisAlignedBox bbox = mEntity->getBoundingBox();

	Ogre::Vector3 offset = bbox.getMaximum() - bbox.getCenter(); // Radius of bounding sphere
	Ogre::Vector3 center = bbox.getCenter();

	mCamera->setPosition( center );
	float oneOverSine = 1.0f / (float)Ogre::Math::Tan( mCamera->getFOVy().valueRadians()/2.0 );
	float distanceToCenter = offset.length() * oneOverSine; // (adjacent / opposite) * opposite = adjacent
	mCamera->move( Ogre::Vector3(1, 1, 1).normalisedCopy() * distanceToCenter);
	mCamera->lookAt( center );
}

void PhysicsViewport::replaceMesh( const std::string &name )
{
	if( mEntity ){
		Lit::Root::SceneManager()->removeEntity( name );
	}
	mEntity = Lit::Root::SceneManager()->createEntity( name, NULL, mSceneManager );
	fitEntity( );
}